package com.devunion.reader.client.core;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.client.rpc.SerializationException;

/**
 * @author Timoshenko Alexander 12.05.2009 : 15:44:32
 */
public abstract class AsyncCommand<T> implements AsyncCallback<T> {
    private Loading loading = new Loading();

    public void run() {
        loading.showLoading();
        attempt();
    }

    public abstract void attempt();

    public abstract void oncapture(T value);

    public void hideLoading() {
        loading.hide();
    }

    public void onFailure(Throwable error) {
        hideLoading();
        try {
            throw error;
        } catch (InvocationException invocationException) {
            Window.alert("A fatal error occurred, you should login " +
                    "again or contact Technical Support");
        } catch (IncompatibleRemoteServiceException remoteServiceException) {
            Window.alert("A fatal error occurred, you should login " +
                    "again or contact Technical Support");
        } catch (SerializationException serializationException) {
            Window.alert("A fatal error occurred, you should login " +
                    "again or contact Technical Support");
        } catch (Throwable throwable) {
            String message = throwable.getLocalizedMessage();

            if (message == null) {
                message = throwable.getMessage();
            }

            if (message == null) {
                message = throwable.getClass().getName();
            }

            if (Window.confirm("An error occured:\n" + message + "\n" +
                    "You may retry this operation by clicking 'OK'.\n" +
                    "However if the error persists, contact Technical Support.")) {

                attempt();
            }
        }
    }

    public void onSuccess(T t) {
        try {
            oncapture(t);
        } catch (RuntimeException error) {
            onFailure(error);
        } finally {
            loading.hide();
        }
    }
}
